package com.ego.product.service.impl;

import com.alibaba.fastjson.JSON;
import com.ego.common.constant.CartConstant;
import com.ego.common.constant.CouponConstant;
import com.ego.common.constant.ProductConstant;
import com.ego.common.constant.SystemConstant;
import com.ego.common.exception.GlobalException;
import com.ego.common.to.member.MemberGroupTo;
import com.ego.product.interceptor.IndexInterceptor;
import com.ego.product.po.SkuInfo;
import com.ego.product.service.CartService;
import com.ego.product.service.SkuInfoService;
import com.ego.product.service.SkuSaleAttrValueService;
import com.ego.common.vo.product.CartUpdateVo;
import com.ego.common.vo.product.CartVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

/**
 * @program: ego
 * @description:
 * @author: KamTang
 * @create: 2022-12-18 08:40
 **/
@Service("cartService")
@Slf4j
public class CartServiceImpl implements CartService {

    @Autowired
    private ThreadPoolExecutor executor;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private SkuInfoService skuInfoService;
    @Autowired
    private SkuSaleAttrValueService skuSaleAttrValueService;

    @Override
    public CartVo.CartItem addToCart(Long skuId, Integer count) throws ExecutionException, InterruptedException {
        BoundHashOperations<String, Object, Object> cartOption = getCartOption(false);

        // 先判断购物车中是否有该商品，如果有则无需执行添加的操作，只需要增加商品数量即可。
        Object goodCache = cartOption.get(skuId.toString());
        if (ObjectUtils.isNotEmpty(goodCache)) {
            CartVo.CartItem cartItem = JSON.parseObject((String) goodCache, CartVo.CartItem.class);
            cartItem.setCount(cartItem.getCount() + count);
            cartOption.put(skuId.toString(), JSON.toJSONString(cartItem));
            return cartItem;
        } else {
            // 异步获取skuInfo信息
            CompletableFuture<SkuInfo> skuInfoTask = CompletableFuture
                    .supplyAsync(() -> skuInfoService.getById(skuId), executor);

            // 异步获取sku销售属性
            CompletableFuture<List<String>> saleAttrTask = CompletableFuture
                    .supplyAsync(() -> skuSaleAttrValueService.gets(skuId));

            // 等待前面两个任务都完成才能继续往下执行
            CompletableFuture.allOf(skuInfoTask, saleAttrTask).get();

            // 将商品添加到购物车中
            CartVo.CartItem cartItem = new CartVo.CartItem();
            cartItem.setSkuId(skuInfoTask.get().getSkuId());
            cartItem.setSelected(true);
            cartItem.setTitle(skuInfoTask.get().getSkuTitle());
            cartItem.setImage(skuInfoTask.get().getSkuDefaultImg());
            cartItem.setSkuAttrs(saleAttrTask.get());
            cartItem.setPrice(skuInfoTask.get().getPrice());
            cartItem.setCount(count);

            String cartItemJson = JSON.toJSONString(cartItem);
            cartOption.put(skuId.toString(), cartItemJson);

            return cartItem;
        }
    }

    @Override
    public CartVo get(MemberGroupTo memberInfo) throws ExecutionException, InterruptedException {
        MemberGroupTo memberGroup;
        if (ObjectUtils.isEmpty(memberInfo)) {
            memberGroup = IndexInterceptor.threadLocal.get();
        } else {
            memberGroup = memberInfo;
        }
        String userKey = CartConstant.CART_PREFIX + memberGroup.getUserKey();
        CartVo cartVo = new CartVo();
        // 已登录
        if (ObjectUtils.isNotEmpty(memberGroup) && memberGroup.getUserId() != null) {
            String cartKey = CartConstant.CART_PREFIX + memberGroup.getUserId();
            // 如果临时购物车中没有商品还没有被合并
            List<CartVo.CartItem> tempCartItems = getItem(userKey);
            if (!CollectionUtils.isEmpty(tempCartItems)) {
                // 合并
                for (CartVo.CartItem tempCartItem : tempCartItems) {
                    addToCart(tempCartItem.getSkuId(), tempCartItem.getCount());
                }
                // 合并完临时购物车之后将临时购物车中的数据删除
                clearCart(userKey);
            }
            // 获取登录后的购物数据【包含临时购物车中的数据】
            List<CartVo.CartItem> cartItems = getItem(cartKey);
            cartVo.setItems(cartItems);

        } else {
            List<CartVo.CartItem> cartItems = getItem(userKey);
            // 这里有数据就有，没有什么都不做
            cartVo.setItems(cartItems);
        }
        // 合并秒杀商品
        List<CartVo.CartItem> seckillCartItems = getItem(CouponConstant.CART_SECKILL_CACHE_PREFIX + memberGroup.getUserId());
        if (!CollectionUtils.isEmpty(seckillCartItems)) {
            List<CartVo.CartItem> promotionItems = seckillCartItems.stream().peek(item -> item.setPromotion(1))
                    .collect(Collectors.toList());
            if (CollectionUtils.isEmpty(cartVo.getItems())) {
                cartVo.setItems(promotionItems);
            } else {
                cartVo.getItems().addAll(promotionItems);
            }
        }
        return cartVo;
    }

    @Override
    public void clearCart(String cartKey) {
        stringRedisTemplate.delete(cartKey);
    }

    @Override
    public void update(CartUpdateVo cartVo) {
        BoundHashOperations<String, Object, Object> cartOption;
        if (cartVo.getPromotion() == ProductConstant.PromotionEnum.PROMOTION.getCode()) {
            // 修改数量
            if (cartVo.getSelected() == null) {
                throw new GlobalException(SystemConstant.Status.COUPON_EXCEPTION.getMsg());
            } else {
                cartOption = getCartOption(true);
            }
        } else {
            cartOption = getCartOption(false);
        }
        CartVo.CartItem cartItem = getItem(cartVo.getSkuId());
        cartItem.update(cartVo);
        cartOption.put(cartVo.getSkuId().toString(), JSON.toJSONString(cartItem));
    }

    @Override
    public void delete(Long skuId, Integer promotion) {
        BoundHashOperations<String, Object, Object> cartOption;
        if (promotion == ProductConstant.PromotionEnum.PROMOTION.getCode()) {
            cartOption = getCartOption(true);
        } else {
            cartOption = getCartOption(false);
        }
        cartOption.delete(skuId.toString());
    }

    @Override
    public List<CartVo.CartItem> getCurrentUserCartItem(Long memberId) {
        if (memberId != null) {
            List<CartVo.CartItem> cartItems = getItem(CartConstant.CART_PREFIX + memberId);
            log.info("CartServiceImpl.cartItems => {}", cartItems);
            List<CartVo.CartItem> seckillCartItems = getItem(CouponConstant.CART_SECKILL_CACHE_PREFIX + memberId);
            log.info("CartServiceImpl.seckillCartItems => {}", seckillCartItems);
            if (!CollectionUtils.isEmpty(seckillCartItems)) {
                List<CartVo.CartItem> promotionItems = seckillCartItems.stream().peek(item -> item.setPromotion(1))
                        .collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(cartItems)) {
                    List<CartVo.CartItem> res = cartItems.stream().filter(CartVo.CartItem::getSelected)
                            .peek(item -> skuInfoService.getById(item.getSkuId())).collect(Collectors.toList());
                    res.addAll(promotionItems);
                    return res;
                } else {
                    return promotionItems;
                }
            } else {
                return cartItems;
            }
        }
        return null;
    }

    /**
     * 获取我们需要操作的购物车
     * @param promotion 是否是参与活动
     */
    private BoundHashOperations<String, Object, Object> getCartOption(boolean promotion) {
        // 使用拦截器获取用户登录状态：已登录or未登录
        MemberGroupTo memberGroup = IndexInterceptor.threadLocal.get();
        log.info("threadLocal.get => {}", memberGroup);
        String cartKey;
        if (ObjectUtils.isNotEmpty(memberGroup) && memberGroup.getUserId() != null) {
            if (promotion) {
                cartKey = CouponConstant.CART_SECKILL_CACHE_PREFIX + memberGroup.getUserId();
            } else {
                cartKey = CartConstant.CART_PREFIX + memberGroup.getUserId();
            }
        } else {
            // 使用当前浏览器Cookie值
            cartKey = CartConstant.CART_PREFIX + memberGroup.getUserKey();
        }
        return stringRedisTemplate.boundHashOps(cartKey);
    }

    /**
     * 根据key获取购物项
     * @param key 存储在缓存中的key
     * @return @see
     * @see CartVo.CartItem
     */
    private List<CartVo.CartItem> getItem(String key) {
        BoundHashOperations<String, Object, Object> hashOps = stringRedisTemplate.boundHashOps(key);
        List<Object> values = hashOps.values();
        if (!CollectionUtils.isEmpty(values)) {
            return values.stream()
                    .map(value -> JSON.parseObject(value.toString(), CartVo.CartItem.class))
                    .collect(Collectors.toList());
        }
        return null;
    }

    /**
     * 根据skuId获取具体购物项
     * @param skuId skuId
     * @return @see
     * @see CartVo.CartItem
     */
    private CartVo.CartItem getItem(Long skuId) {
        BoundHashOperations<String, Object, Object> cartOption = getCartOption(false);
        String cartItemJson = (String) cartOption.get(skuId.toString());
        return JSON.parseObject(cartItemJson, CartVo.CartItem.class);
    }
}
